package com.my.core.util.file;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Slf4j
@Component
public class FileInfoManager {
    //直接在项目根目录，目前就是timo-tool/data/
    private static final String FILE_PATH = "./data/file_infos.txt";
    private final ReentrantLock lock = new ReentrantLock();
    // 修改ObjectMapper配置，禁用格式化输出（关键修复）
    private final ObjectMapper objectMapper = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .disable(SerializationFeature.INDENT_OUTPUT); // 禁用缩进格式化，确保单行紧凑JSON

    /**
     * 添加文件信息到txt文件
     */
    public void addFileInfos(List<FileInfo> fileInfos) {
        if (fileInfos == null || fileInfos.isEmpty()) {
            return;
        }

        lock.lock();
        try {
            File dataDir = new File("./data");
            if (!dataDir.exists() && !dataDir.mkdirs()) {
                log.error("无法创建data目录");
                return;
            }

            File file = new File(FILE_PATH);
            List<FileInfo> existingInfos = readAllFileInfos();
            List<String> existingIds = existingInfos.stream()
                    .map(FileInfo::getId)
                    .collect(Collectors.toList());

            try (BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(
                            Files.newOutputStream(
                                    file.toPath(),
                                    StandardOpenOption.CREATE,
                                    StandardOpenOption.APPEND
                            ),
                            StandardCharsets.UTF_8))) {

                for (FileInfo info : fileInfos) {
                    if (!existingIds.contains(info.getId())) {
                        // 确保写入的JSON是完整的
                        String json = objectMapper.writeValueAsString(info);
                        writer.write(json);
                        writer.newLine();
                    }
                }
            }

        } catch (IOException e) {
            log.error("添加文件信息失败", e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 从txt文件中删除指定ID的文件信息
     */
    public void removeFileInfos(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }

        lock.lock();
        try {
            File file = new File(FILE_PATH);
            if (!file.exists()) {
                return;
            }

            // 先读取并过滤有效数据
            List<FileInfo> allInfos = readAllFileInfos();
            List<FileInfo> remainingInfos = allInfos.stream()
                    .filter(info -> !ids.contains(info.getId()))
                    .collect(Collectors.toList());

            // 写回清理后的数据
            try (BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(
                            Files.newOutputStream(file.toPath(), StandardOpenOption.TRUNCATE_EXISTING),
                            StandardCharsets.UTF_8))) {

                for (FileInfo info : remainingInfos) {
                    writer.write(objectMapper.writeValueAsString(info));
                    writer.newLine();
                }
            }

        } catch (IOException e) {
            log.error("删除文件信息失败", e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 读取所有文件信息（增加容错处理）
     */
    public List<FileInfo> readAllFileInfos() {
        lock.lock();
        try {
            File file = new File(FILE_PATH);
            if (!file.exists()) {
                return new ArrayList<>();
            }

            List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8).stream()
                    .map(String::trim)
                    .filter(line -> !line.isEmpty())
                    // 过滤明显无效的行（如单独的{、}、逗号或字段）
                    .filter(line -> !line.matches("^[{}.,]$") && !line.matches("^\"[a-zA-Z0-9]+\"\\s*:"))
                    .collect(Collectors.toList());

            List<FileInfo> validInfos = new ArrayList<>();
            List<String> invalidLines = new ArrayList<>();

            for (String line : lines) {
                try {
                    FileInfo info = objectMapper.readValue(line, FileInfo.class);
                    validInfos.add(info);
                } catch (Exception e) {
                    log.error("解析无效JSON行: {}", line, e);
                    invalidLines.add(line);
                }
            }

            // 清理无效数据
            if (!invalidLines.isEmpty()) {
                log.warn("清理 {} 条无效数据", invalidLines.size());
                cleanInvalidData(validInfos, invalidLines);
            }

            return validInfos;

        } catch (IOException e) {
            log.error("读取文件信息失败", e);
            return new ArrayList<>();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 清理无效数据并备份
     */
    private void cleanInvalidData(List<FileInfo> validInfos, List<String> invalidLines) throws IOException {
        // 备份无效数据
        File backupFile = new File("./data/file_infos_invalid_backup.txt");
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(
                        Files.newOutputStream(backupFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND),
                        StandardCharsets.UTF_8))) {
            writer.write("===== " + new java.util.Date() + " 备份的无效数据 =====");
            writer.newLine();
            for (String line : invalidLines) {
                writer.write(line);
                writer.newLine();
            }
        }

        // 只保留有效数据
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(
                        Files.newOutputStream(new File(FILE_PATH).toPath(), StandardOpenOption.TRUNCATE_EXISTING),
                        StandardCharsets.UTF_8))) {
            for (FileInfo info : validInfos) {
                writer.write(objectMapper.writeValueAsString(info));
                writer.newLine();
            }
        }
    }
}
